import { readFileSync, existsSync } from 'fs';
import { resolve } from 'path';

export interface ServerConfig {
  server: {
    host: string;
    port: number;
    protocol: string;
    memory: {
      maxOldSpaceSize: number;
      enableGC: boolean;
      autoOptimizeForLargeRepository: boolean;
    };
  };
  mcp: {
    protocolVersion: string;
    sessionTimeout: number;
    maxConcurrentSessions: number;
    enableCors: boolean;
    enableStreaming: boolean;
  };
  maven: {
    localRepository: string;
    repositories: string[];
    timeout: number;
    maxDownloadSize: string;
  };
  decompiler: {
    engines: string[];
    defaultEngine: string;
    timeout: number;
    maxConcurrentJobs: number;
    cacheResults: boolean;
  };
  logging: {
    level: string;
    enableRequestLogging: boolean;
    logFile: string;
  };
  security: {
    enableAuth: boolean;
    corsOrigins: string[];
    rateLimiting: {
      enabled: boolean;
      windowMs: number;
      maxRequests: number;
    };
  };
}

class ConfigManager {
  private config: ServerConfig;
  private configPaths = [
    './config/server.json',
    './server.json',
    './config.json'
  ];

  constructor() {
    this.config = this.loadConfig();
  }

  private loadConfig(): ServerConfig {
    // Try to load from config file
    for (const configPath of this.configPaths) {
      const fullPath = resolve(configPath);
      if (existsSync(fullPath)) {
        try {
          const configData = readFileSync(fullPath, 'utf-8');
          const fileConfig = JSON.parse(configData);
          console.log(`📝 Loaded configuration from: ${configPath}`);
          return this.mergeWithDefaults(fileConfig);
        } catch (error) {
          console.warn(`⚠️  Failed to load config from ${configPath}:`, error);
        }
      }
    }

    console.log('📝 Using default configuration with environment variables');
    return this.getDefaultConfig();
  }

  private mergeWithDefaults(fileConfig: any): ServerConfig {
    const defaults = this.getDefaultConfig();
    
    return {
      server: {
        host: fileConfig.server?.host || defaults.server.host,
        port: fileConfig.server?.port || defaults.server.port,
        protocol: fileConfig.server?.protocol || defaults.server.protocol,
        memory: {
          maxOldSpaceSize: fileConfig.server?.memory?.maxOldSpaceSize || defaults.server.memory.maxOldSpaceSize,
          enableGC: fileConfig.server?.memory?.enableGC ?? defaults.server.memory.enableGC,
          autoOptimizeForLargeRepository: fileConfig.server?.memory?.autoOptimizeForLargeRepository ?? defaults.server.memory.autoOptimizeForLargeRepository
        }
      },
      mcp: {
        protocolVersion: fileConfig.mcp?.protocolVersion || defaults.mcp.protocolVersion,
        sessionTimeout: fileConfig.mcp?.sessionTimeout || defaults.mcp.sessionTimeout,
        maxConcurrentSessions: fileConfig.mcp?.maxConcurrentSessions || defaults.mcp.maxConcurrentSessions,
        enableCors: fileConfig.mcp?.enableCors ?? defaults.mcp.enableCors,
        enableStreaming: fileConfig.mcp?.enableStreaming ?? defaults.mcp.enableStreaming
      },
      maven: {
        localRepository: fileConfig.maven?.localRepository || defaults.maven.localRepository,
        repositories: fileConfig.maven?.repositories || defaults.maven.repositories,
        timeout: fileConfig.maven?.timeout || defaults.maven.timeout,
        maxDownloadSize: fileConfig.maven?.maxDownloadSize || defaults.maven.maxDownloadSize
      },
      decompiler: {
        engines: fileConfig.decompiler?.engines || defaults.decompiler.engines,
        defaultEngine: fileConfig.decompiler?.defaultEngine || defaults.decompiler.defaultEngine,
        timeout: fileConfig.decompiler?.timeout || defaults.decompiler.timeout,
        maxConcurrentJobs: fileConfig.decompiler?.maxConcurrentJobs || defaults.decompiler.maxConcurrentJobs,
        cacheResults: fileConfig.decompiler?.cacheResults ?? defaults.decompiler.cacheResults
      },
      logging: {
        level: fileConfig.logging?.level || defaults.logging.level,
        enableRequestLogging: fileConfig.logging?.enableRequestLogging ?? defaults.logging.enableRequestLogging,
        logFile: fileConfig.logging?.logFile || defaults.logging.logFile
      },
      security: {
        enableAuth: fileConfig.security?.enableAuth ?? defaults.security.enableAuth,
        corsOrigins: fileConfig.security?.corsOrigins || defaults.security.corsOrigins,
        rateLimiting: {
          enabled: fileConfig.security?.rateLimiting?.enabled ?? defaults.security.rateLimiting.enabled,
          windowMs: fileConfig.security?.rateLimiting?.windowMs || defaults.security.rateLimiting.windowMs,
          maxRequests: fileConfig.security?.rateLimiting?.maxRequests || defaults.security.rateLimiting.maxRequests
        }
      }
    };
  }

  private getDefaultConfig(): ServerConfig {
    return {
      server: {
        host: process.env.HOST || 'localhost',
        port: parseInt(process.env.PORT || '3000'),
        protocol: process.env.PROTOCOL || 'http',
        memory: {
          maxOldSpaceSize: parseInt(process.env.NODE_MAX_OLD_SPACE_SIZE || '4096'),
          enableGC: process.env.NODE_ENABLE_GC !== 'false',
          autoOptimizeForLargeRepository: process.env.AUTO_OPTIMIZE_MEMORY !== 'false'
        }
      },
      mcp: {
        protocolVersion: process.env.MCP_PROTOCOL_VERSION || '2025-03-26',
        sessionTimeout: parseInt(process.env.SESSION_TIMEOUT || '1800000'), // 30 minutes
        maxConcurrentSessions: parseInt(process.env.MAX_CONCURRENT_SESSIONS || '100'),
        enableCors: process.env.ENABLE_CORS !== 'false',
        enableStreaming: process.env.ENABLE_STREAMING !== 'false'
      },
      maven: {
        localRepository: process.env.MAVEN_LOCAL_REPOSITORY || '/mnt/d/mavenrepository',
        repositories: process.env.MAVEN_REPOSITORIES?.split(',') || [
          'https://repo1.maven.org/maven2/',
          'https://maven.google.com/'
        ],
        timeout: parseInt(process.env.MAVEN_TIMEOUT || '30000'),
        maxDownloadSize: process.env.MAX_DOWNLOAD_SIZE || '100MB'
      },
      decompiler: {
        engines: process.env.DECOMPILER_ENGINES?.split(',') || ['cfr', 'fernflower'],
        defaultEngine: process.env.DEFAULT_DECOMPILER_ENGINE || 'cfr',
        timeout: parseInt(process.env.DECOMPILER_TIMEOUT || '30000'),
        maxConcurrentJobs: parseInt(process.env.MAX_CONCURRENT_DECOMPILE_JOBS || '5'),
        cacheResults: process.env.CACHE_DECOMPILE_RESULTS !== 'false'
      },
      logging: {
        level: process.env.LOG_LEVEL || 'info',
        enableRequestLogging: process.env.ENABLE_REQUEST_LOGGING !== 'false',
        logFile: process.env.LOG_FILE || 'logs/mcp-server.log'
      },
      security: {
        enableAuth: process.env.ENABLE_AUTH === 'true',
        corsOrigins: process.env.CORS_ORIGINS?.split(',') || ['*'],
        rateLimiting: {
          enabled: process.env.ENABLE_RATE_LIMITING === 'true',
          windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000'), // 15 minutes
          maxRequests: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100')
        }
      }
    };
  }

  public getConfig(): ServerConfig {
    return this.config;
  }

  public getServerUrl(): string {
    return `${this.config.server.protocol}://${this.config.server.host}:${this.config.server.port}`;
  }

  public getMcpEndpoint(): string {
    return `${this.getServerUrl()}/mcp`;
  }

  public getHealthEndpoint(): string {
    return `${this.getServerUrl()}/health`;
  }

  public getInfoEndpoint(): string {
    return `${this.getServerUrl()}/mcp/info`;
  }

  public updateConfig(updates: Partial<ServerConfig>): void {
    this.config = { ...this.config, ...updates };
  }

  public printConfig(): void {
    console.log('🔧 Current Configuration:');
    console.log(`   Server: ${this.getServerUrl()}`);
    console.log(`   MCP Endpoint: ${this.getMcpEndpoint()}`);
    console.log(`   Protocol Version: ${this.config.mcp.protocolVersion}`);
    console.log(`   CORS: ${this.config.mcp.enableCors ? 'Enabled' : 'Disabled'}`);
    console.log(`   Streaming: ${this.config.mcp.enableStreaming ? 'Enabled' : 'Disabled'}`);
    console.log(`   Session Timeout: ${this.config.mcp.sessionTimeout}ms`);
    console.log(`   Memory Limit: ${this.config.server.memory.maxOldSpaceSize}MB`);
    console.log(`   GC Enabled: ${this.config.server.memory.enableGC ? 'Yes' : 'No'}`);
    console.log(`   Auto Optimize: ${this.config.server.memory.autoOptimizeForLargeRepository ? 'Yes' : 'No'}`);
    console.log(`   Maven Repository: ${this.config.maven.localRepository}`);
    console.log(`   Decompiler Engine: ${this.config.decompiler.defaultEngine}`);
  }
}

export const configManager = new ConfigManager();
export const config = configManager.getConfig();